﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using LGE;

namespace MagicFight
{
    public static class Def // DEF = DEFINITIONS
    {
        public static List<String> ButtonIndex = new List<String>() { KeyMap.A, KeyMap.B, KeyMap.X, KeyMap.Y, KeyMap.LS, KeyMap.RS, KeyMap.LT, KeyMap.RT };

        public static List<MagicDef> MagicDefs = new List<MagicDef>();

        static Def()
        {
            #region Arcane
            MagicDefs.Add(new ArcaneShotDef()); MagicDefs.Add(new ArcaneMissileDef());
            MagicDefs.Add(new ArcaneBombDef()); MagicDefs.Add(new CounterDef());
            MagicDefs.Add(new ManaDrainDef()); MagicDefs.Add(new RicochetDef());
            MagicDefs.Add(new EvocationDef()); MagicDefs.Add(new ArcaneBeamDef());
            #endregion
            #region Holy
            MagicDefs.Add(new HolyLightDef()); MagicDefs.Add(new ConsecrationDef());
            MagicDefs.Add(new HolyPowerDef()); MagicDefs.Add(new HolySacrificeDef());
            MagicDefs.Add(new GratitudeDef()); MagicDefs.Add(new DevotionDef());
            MagicDefs.Add(new RejuvenationDef()); MagicDefs.Add(new GodBlessDef());
            #endregion
            #region Protection
            MagicDefs.Add(new BlockDef()); MagicDefs.Add(new ReflectDef());
            MagicDefs.Add(new ManaShieldDef()); MagicDefs.Add(new HardenDef());
            MagicDefs.Add(new ArcaneShotDef()); MagicDefs.Add(new ArcaneShotDef());
            MagicDefs.Add(new ArcaneShotDef()); MagicDefs.Add(new ArcaneShotDef());
            #endregion
            #region Elemental
            MagicDefs.Add(new ArcaneShotDef()); MagicDefs.Add(new ArcaneShotDef());
            MagicDefs.Add(new ArcaneShotDef()); MagicDefs.Add(new ArcaneShotDef());
            MagicDefs.Add(new ArcaneShotDef()); MagicDefs.Add(new ArcaneShotDef());
            MagicDefs.Add(new ArcaneShotDef()); MagicDefs.Add(new ArcaneShotDef());
            #endregion
        }

        public abstract class MagicDef
        {
            public String Name;
            public MagicType Type;
            public int ManaCost;
            public int PointCost;
            public int CastTime;
            public String Description;
            public Texture2D Logo;
            public abstract Magic Cast(Character caster);

            public MagicDef(String Name, MagicType Type, int ManaCost, int PointCost, int CastTime, String Description)
            {
                this.Name = Name;
                this.Type = Type;
                this.ManaCost = ManaCost;
                this.PointCost = PointCost;
                this.CastTime = CastTime;
                this.Description = Description;
                Logo = Engine.Load<Texture2D>("Images\\Logo\\" + Type.ToString() + "\\" + Name.Replace(" ", ""));
            }
        }

        #region ArcaneDefs
        public class ArcaneShotDef : MagicDef
        {
            public const int N = 0;
            public static int Damage = 5;
            public override Magic Cast(Character c) { return new ArcaneShot(c); }
            public ArcaneShotDef()
                : base(
                    /* Name      */ "Arcane Shot",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 5,
                    /* PointCost */ 0,
                    /* CastTime  */ 0,
                    /*Description*/ "Atira um projétil e dá 5 de dano.") { }
        }

        public class ArcaneMissileDef : MagicDef
        {
            public const int N = 1;
            public static int Damage = 5;
            public override Magic Cast(Character c) { return new ArcaneMissile(c); }
            public ArcaneMissileDef()
                : base(
                    /* Name      */ "Arcane Missile",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 0,
                    /* PointCost */ -1,
                    /* CastTime  */ 0,
                    /*Description*/ "Atira um projétil e dá 5 de dano.") { }
        }

        public class ArcaneBombDef : MagicDef
        {
            public const int N = 2;
            public static int Damage = 10;
            public static int Radius = 100; // Raio da explosão
            public static int Timer = 5000; // Explode sozinha neste tempo caso ninguém encoste

            public override Magic Cast(Character c) { return new ArcaneBomb(c); }
            public ArcaneBombDef()
                : base(
                    /* Name      */ "Arcane Bomb",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 15,
                    /* PointCost */ 1,
                    /* CastTime  */ 0,
                    /*Description*/ "Deixa uma bomba no chão, quem encostar toma 5 de dano.") { }
        }

        public class CounterDef : MagicDef
        {
            public const int N = 3;
            public static int Radius = 200; // Raio do counter
            public static int PointGain = 1; // Quantidade de pontos que ganha caso consiga cortar algum cast

            public override Magic Cast(Character c) { return new Counter(c); }
            public CounterDef()
                : base(
                    /* Name      */ "Counter",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 15,
                    /* PointCost */ 0,
                    /* CastTime  */ 0,
                    /*Description*/ "Se algum jogador está castando uma magia a sua volta (raio médio) ele pára de castar e perde a mana e os pontos da magia. Se conseguiu algum counter, ganha 1a.") { }
        }

        public class ManaDrainDef : MagicDef
        {
            public const int N = 4;
            public static int Radius = 200; // Raio do drain
            public static int ManaDrain = 15; // Quantidade drenada

            public override Magic Cast(Character c) { return new ManaDrain(c); }
            public ManaDrainDef()
                : base(
                    /* Name      */ "Mana Drain",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 0,
                    /* PointCost */ -1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Drena 15mp do inimigo e passa para o caster.") { }
        }

        public class RicochetDef : MagicDef
        {
            public const int N = 5;
            public static int Damage = 10;

            public override Magic Cast(Character c) { return new Ricochet(c); }
            public RicochetDef()
                : base(
                    /* Name      */ "Ricochet",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 20,
                    /* PointCost */ 1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Dispara 8 mísseis ao redor do caster que ricocheteia nas paredes, durando 5s. Se encostar em alguém (mesmo no caster) causa 10 de dano.") { }
        }

        public class EvocationDef : MagicDef
        {
            public const int N = 6;
            public static int GainInterval = 2000; // Intervalo em ms entre cada ganho; a duração máxima é o CastTime!
            public static int PointGain = 1; // Ganho de pontos por intervalo
            public static int ManaGain = 15; // Ganho de mana por intervalo

            public override Magic Cast(Character c) { return new Evocation(c); }
            public EvocationDef()
                : base(
                    /* Name      */ "Evocation",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 0,
                    /* PointCost */ 0,
                    /* CastTime  */ 6000,
                    /*Description*/ "Não tem cast mas fica parado canalizando energia até o caster receber dano. A cada 2s de canalização, ganha 15m e 1a. O tempo máximo de canalização é 6s. O caster pode interromper a canalização usando novamente o Evocation.") { }
        }

        public class ArcaneBeamDef : MagicDef
        {
            public const int N = 7;
            public static int Duration = 4000; // duração total do raio
            public static int Interval = 500; // intervalo de tempo que um alvo tem q ficar no raio para receber dano
            public static int Damage = 10; // dano que um alvo recebe a cada intervalo

            public override Magic Cast(Character c) { return new ArcaneBeam(c); }
            public ArcaneBeamDef()
                : base(
                    /* Name      */ "Arcane Beam",
                    /* Type      */ MagicType.Arcane,
                    /* ManaCost  */ 30,
                    /* PointCost */ 0, // -2
                    /* CastTime  */ 1000,
                    /*Description*/ "Atira um raio de energia a frente do caster causando " + Damage + " de dano em quem encostar a cada " + ((double)Interval / 1000).ToString("0.0") + "s.") { }
        }
        #endregion

        #region HolyDefs
        public class HolyLightDef : MagicDef
        {
            public const int N = 8;
            public static int HealingAmount = 15;

            public override Magic Cast(Character c) { return new HolyLight(c); }
            public HolyLightDef()
                : base(
                    /* Name      */ "Holy Light",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 20,
                    /* PointCost */ -1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Cura " + HealingAmount + " de vida do caster.") { }
        }

        public class ConsecrationDef : MagicDef
        {
            public const int N = 9;
            public static int HealingAmount = 5;
            public static int Damage = 5;
            public static int Duration = 5000;
            public static int Range = 200;
            public static int Interval = 500;

            public override Magic Cast(Character c) { return new Consecration(c); }
            public ConsecrationDef()
                : base(
                    /* Name      */ "Consecration",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 20,
                    /* PointCost */ 1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Consagra o chão (raio " + Range + "), curando " + HealingAmount + "HP para cada " + ((double)Interval / 1000).ToString("0.0") + "s que o caster permanecer dentro dele, e causando " + Damage + "HP para cada segundo que um oponente permanecer dentro dele. Dura " + ((double)Duration / 1000).ToString("0.0") + "s.") { }
        }

        public class HolyPowerDef : MagicDef
        {
            public const int N = 10;
            public static float Multiplier = .5f;
            public static int Duration = 10000;

            public override Magic Cast(Character c) { return new HolyPower(c); }
            public HolyPowerDef()
                : base(
                    /* Name      */ "Holy Power",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 10,
                    /* PointCost */ -1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Todo dano causado pelo caster é aumentado em " + (Multiplier * 100) + "%. Dura " + ((double)Duration / 1000).ToString("0.0") + "s.") { }
        }

        public class HolySacrificeDef : MagicDef
        {
            public const int N = 11;
            public static int HPloss = 10;
            public static int MPgain = 7;

            public override Magic Cast(Character c) { return new HolySacrifice(c); }
            public HolySacrificeDef()
                : base(
                    /* Name      */ "Holy Sacrifice",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 0,
                    /* PointCost */ 1,
                    /* CastTime  */ 0,
                    /*Description*/ "Sacrifica " + HPloss + "HP para ganhar " + MPgain + "MP e 1 holy point.") { }
        }

        public class GratitudeDef : MagicDef
        {
            public const int N = 12;
            public static int HPgain = 5;

            public override Magic Cast(Character c) { return new Gratitude(c); }
            public GratitudeDef()
                : base(
                    /* Name      */ "Gratitude",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 10,
                    /* PointCost */ 1,
                    /* CastTime  */ 0,
                    /*Description*/ "Cura " + HPgain + "HP de todos jogadores em jogo.") { }
        }

        public class DevotionDef : MagicDef
        {
            public const int N = 13;
            public static int PointGain = 1;

            public override Magic Cast(Character c) { return new Devotion(c); }
            public DevotionDef()
                : base(
                    /* Name      */ "Devotion",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 15,
                    /* PointCost */ 0,
                    /* CastTime  */ 2000,
                    /*Description*/ "Ganha um ponto de cada tipo de magia.") { }
        }

        public class RejuvenationDef : MagicDef
        {
            public const int N = 14;
            public static int HPGain = 3;
            public static int Duration = 10000;
            public static int Interval = 1000;

            public override Magic Cast(Character c) { return new Rejuvenation(c); }
            public RejuvenationDef()
                : base(
                    /* Name      */ "Rejuvenation",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 20,
                    /* PointCost */ -1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Se cura " + HPGain + "HP por segundo. Dura " + (Duration / 1000).ToString("0.0") + "s.") { }
        }

        public class GodBlessDef : MagicDef
        {
            public const int N = 15;
            public static int Duration = 10000;
            public static float Multiplier = 1f;

            public override Magic Cast(Character c) { return new GodBless(c); }
            public GodBlessDef()
                : base(
                    /* Name      */ "God Bless",
                    /* Type      */ MagicType.Holy,
                    /* ManaCost  */ 50,
                    /* PointCost */ -3,
                    /* CastTime  */ 3000,
                    /*Description*/ "Todo dano recebido é reduzido a zero, e todo dano causado é aumentado em " + (Multiplier * 100) + "%. Dura " + (Duration / 1000).ToString("0.0") + "s.") { }
        }
        #endregion

        #region ProtectionDefs
        public class BlockDef : MagicDef
        {
            public const int N = 16;
            public static int Duration = 300;
            public static int PointGain = 1;
            public static int Range = 70;

            public override Magic Cast(Character c) { return new Block(c); }
            public BlockDef()
                : base(
                    /* Name      */ "Block",
                    /* Type      */ MagicType.Protection,
                    /* ManaCost  */ 5,
                    /* PointCost */ 0,
                    /* CastTime  */ 0,
                    /*Description*/ "Nos próximos " + (Duration / 1000).ToString("0.0") + "s, qualquer projétil que acertar o personagem, é destruido e não dá dano. Se conseguiu bloquear algum projétil, ganha " + PointGain + "p.") { }
        }
        
        public class ReflectDef : MagicDef
        {
            public const int N = 17;
            public static int Duration = 300;
            public static int PointGain = 1;
            public static int Range = 65;

            public override Magic Cast(Character c) { return new Reflect(c); }
            public ReflectDef()
                : base(
                    /* Name      */ "Reflect",
                    /* Type      */ MagicType.Protection,
                    /* ManaCost  */ 5,
                    /* PointCost */ 0,
                    /* CastTime  */ 0,
                    /*Description*/ "Nos próximos " + (Duration / 1000).ToString("0.0") + "s, qualquer projétil que acertar o personagem, é refletido na direção que o caster do Reflect estiver olhando. Se conseguiu bloquear algum projétil, ganha " + PointGain + "p.") { }
        }

        public class ManaShieldDef : MagicDef
        {
            public const int N = 18;
            public static int Duration = 10000;

            public override Magic Cast(Character c) { return new ManaShield(c); }
            public ManaShieldDef()
                : base(
                    /* Name      */ "Mana Shield",
                    /* Type      */ MagicType.Protection,
                    /* ManaCost  */ 0,
                    /* PointCost */ -3,
                    /* CastTime  */ 0,
                    /*Description*/ "Todo dano recebido é descontado da mana ao invés da vida por " + (Duration / 1000).ToString("0.0") + "s. Se a Mana chegar a zero, o Mana Shield é cancelado. O jogador pode interromper este efeito apertando o botão novamente.") { }
        }

        public class HardenDef : MagicDef
        {
            public const int N = 19;    
            public static float Multiplier = .2f;
            public static int Duration = 5000;

            public override Magic Cast(Character c) { return new Harden(c); }
            public HardenDef()
                : base(
                    /* Name      */ "Harden",
                    /* Type      */ MagicType.Protection,
                    /* ManaCost  */ 10,
                    /* PointCost */ 1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Todo dano recebido é reduzido em " + (Multiplier * 100) + "% por " + (Duration / 1000).ToString("0.0") + "s.") { }
        }

        public class FieldProtectionDef : MagicDef
        {
            public const int N = 20;
            public static float Multiplier = .5f;
            public static int Duration = 15000;
            public static int radius = 100;

            public override Magic Cast(Character c) { return new FieldProtection(c); }
            public FieldProtectionDef()
                : base(
                    /* Name      */ "Field Protection",
                    /* Type      */ MagicType.Protection,
                    /* ManaCost  */ 30,
                    /* PointCost */ 1,
                    /* CastTime  */ 1000,
                    /*Description*/ "Cria um círculo em volta do caster que dura " + (Duration / 1000).ToString("0.0") + "s. Todo dano que qualquer personagem tomar dentro deste círculo é reduzido em " + (Multiplier * 100) + "%. O círculo não acompanha o caster caso este se mova.") { }
        }

        public class RetributionAuraDef : MagicDef
        {
            public const int N = 21;
            public static float Multiplier = .2f;
            public static int Duration = 10000;

            public override Magic Cast(Character c) { return new RetributionAura(c); }
            public RetributionAuraDef()
                : base(
                    /* Name      */ "Retribution Aura",
                    /* Type      */ MagicType.Protection,
                    /* ManaCost  */ 20,
                    /* PointCost */ -2,
                    /* CastTime  */ 1000,
                    /*Description*/ "Durante " + (Duration / 1000).ToString("0.0") + "s todo dano que receber volta " + (Multiplier * 100) + "% pro caster deste dano.") { }
        }
        #endregion
    }
}